﻿namespace Atomic.Events.Queues
{
    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.Collections.Concurrent;

    /// <summary>
    /// 事件队列
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class DefaultEventQueue<T> : BlockingCollection<T>, IQueue<T>
    {
        /// <summary>
        /// 获取项
        /// </summary>
        /// <returns>项</returns>
        public T Get()
        {
            return base.Take();
        }

        /// <summary>
        /// 获得指定数量的项。
        /// </summary>
        /// <param name="count">数量</param>
        /// <returns>项的集合</returns>
        public IEnumerable<T> Get(int count)
        {
            IList<T> items = null;

            count = this.CalculateCount(count);

            if (count > 0)
            {
                items = new List<T>();

                for (int index = 0; index < count; index++)
                {
                    var item = base.Take();

                    if (item != null)
                    {
                        items.Add(item);
                    }
                }
            }

            return items;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public new T[] ToArray()
        {
            return this.ToArray(this.Count);
        }

        /// <summary>
        /// 获得指定数量的数组。
        /// </summary>
        /// <returns>所有项的数组</returns>
        public T[] ToArray(int count)
        {
            return this.Get(count).ToArray();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="item"></param>
        public new void Add(T item)
        {
            base.Add(item);
        }

        /// <summary>
        /// 计算实际获得数。
        /// </summary>
        /// <remarks>
        /// 即：
        /// 使用方想要从队列中获取 1000 个对象。
        /// 但是，队列中只有 100 个对象。
        /// 所以，这里计算并返回的结果就是 100。
        /// </remarks>
        /// <param name="count">请求获取数</param>
        /// <returns></returns>
        private int CalculateCount(int count)
        {
            if (base.Count > 0 && count > 0)
            {
                if (count > base.Count)
                {
                    count = base.Count;
                }

                return count;
            }

            return 0;
        }
    }
}